import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class LearningEngine 
{
	public static Random random;
	public static boolean initGeneration = false;
	public ArrayList<group1_KalahHeuristic> current_generation;
	public static int length = 0;
	public int village_id;
	private GeneticEngine geneticEngine;
	
	
	public LearningEngine(int village_id)  
	{
		current_generation = new ArrayList<group1_KalahHeuristic>();
		this.village_id = village_id;
		geneticEngine = new GeneticEngine(village_id);
		loadCurrentGeneration();
		
	}
	
	public LearningEngine(int village_id, boolean loadCurrentGeneration) {
		current_generation = new ArrayList<group1_KalahHeuristic>();
		this.village_id = village_id;
		geneticEngine = new GeneticEngine(village_id);
		if (loadCurrentGeneration)
			loadCurrentGeneration();
	}

	@SuppressWarnings("unchecked")
	public void saveCurrentGeneration()
	{
		
		System.out.println("WARNING WRITING TO FILE, PLEASE DO NOT END THE PROGRAM!");
		
		FileWriter writer ;
		BufferedWriter bwriter, backupWriter;
		File backupsFolder = new File("village" + village_id + "/backups");
		
		try
		{

			
			String directoryname = "village" + village_id;
			File directory = new File(directoryname);
			
			if (!directory.isDirectory())
			{
				directory.mkdir();
			}
			
			if (!backupsFolder.isDirectory())
			{
				backupsFolder.mkdir();
			}
			
			backupWriter = new BufferedWriter(new FileWriter("village" + village_id + "/backups\\generation"+GeneticVillageSimulator.iteration+".txt"));	
			
			
			String filename = "village" + village_id + "/current_generation.txt";
			
			writer = new FileWriter(filename);
			
			
			bwriter = new BufferedWriter(writer);
			
			//Collections.sort(current_generation, new group1_KalahHeuristic.KalahComparator() );
			
			setLongestHeuristicNameLength(current_generation);
			
			for(group1_KalahHeuristic kh : current_generation)
			{
				String weights;
				
				weights = String.format("%-"+length+"s %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %21.15f %1d wins:%.2f losses:%1d win ratio: %.5f" 
						,kh.name,
						kh.h1_1 , kh.h2_1 , kh.h3_1 , kh.h4_1 , kh.h5_1 , kh.h6_1 , kh.h7_1, kh.h8_1 , kh.h9_1,
						kh.h1_2 , kh.h2_2 , kh.h3_2 , kh.h4_2 , kh.h5_2 , kh.h6_2 , kh.h7_2, kh.h8_2 , kh.h9_2,
						kh.h1_3 , kh.h2_3 , kh.h3_3 , kh.h4_3 , kh.h5_3 , kh.h6_3 , kh.h7_3, kh.h8_3 , kh.h9_3,
						kh.child, kh.wins , kh.losses, kh.wins/kh.gamesPlayed);
				
				kh.resetStats();
				
				bwriter.write(weights);
				bwriter.newLine();
				
				backupWriter.write(weights);
				backupWriter.newLine();
				
			}
			backupWriter.close();
			bwriter.close();
			writer.close();
			
		}
		catch(IOException ioe)
		{
			ioe.printStackTrace();
		}
		finally
		{
			System.out.println("NO LONGER WRITING TO FILE, IT IS NOW OKAY TO END THE PROGRAM!");
		}

	}
	
	public void loadCurrentGeneration()
	{
		
		current_generation.clear();
		
		System.out.println("LOADING CURRENT GENERATION FROM FILE!");
		
		Scanner scanner;
		

		File file;
		
		try
		{
			String directoryname = "village" + village_id;
			File directory = new File(directoryname);
			
			if (!directory.isDirectory())
			{
				directory.mkdir();
			}
			
			String filename = "village" + village_id + "/current_generation.txt";
			file = new File(filename);
			scanner = new Scanner(file);
			int count = 1;
			
			
			while(scanner.hasNextLine())
			{		
				ArrayList<Double> weight_values = new ArrayList<Double>();
				String text = scanner.nextLine();
				
				
				Scanner s1 = new Scanner(text);
				String name;
				boolean firstRun = s1.hasNextDouble();
				
				if (firstRun){
					name = "V"+village_id+"F"+count;
					count++;
				}else
				  name = s1.next();
				
				while(s1.hasNextDouble())
				{
					weight_values.add(new Double(s1.nextDouble()));
				}
				
				group1_KalahHeuristic kh1 = new group1_KalahHeuristic(name,
						weight_values.get(0), weight_values.get(1), weight_values.get(2), weight_values.get(3), weight_values.get(4), weight_values.get(5), weight_values.get(6), weight_values.get(7) , weight_values.get(8),
						weight_values.get(9), weight_values.get(10), weight_values.get(11), weight_values.get(12), weight_values.get(13), weight_values.get(14), weight_values.get(15), weight_values.get(16) , weight_values.get(17),
						weight_values.get(18), weight_values.get(19), weight_values.get(20), weight_values.get(21), weight_values.get(22), weight_values.get(23), weight_values.get(24), weight_values.get(25) , weight_values.get(26),
						(firstRun)? 0 : Integer.parseInt(String.format("%1.0f",weight_values.get(27))) );
				
				current_generation.add(kh1);
			}
			
			scanner.close();
			
			Pattern generation = Pattern.compile("V\\d+G(\\d+)R\\d+");
			Matcher number = generation.matcher(current_generation.get(current_generation.size()-1).name);
			

			if(number.find())
			{
				GeneticVillageSimulator.iteration = Integer.parseInt(number.group(1)); 
			}
			
		}
		catch(IOException ioe)
		{
			System.out.println( "File does not exist, generating a random generation.");
			current_generation = geneticEngine.generate_random_heuristics(30);
			initGeneration = true;
		
		}
		finally
		{
			System.out.println("NO LONGER LOADING FROM FILE!");
			setLongestHeuristicNameLength(current_generation);
		}
	}
	
	
	public static void setLongestHeuristicNameLength(ArrayList<group1_KalahHeuristic> generation){
		length = 0;
		
		for(group1_KalahHeuristic kh : generation)
		{
			if (kh.name.length() > length){
				length = kh.name.length();
			}
		}
	}
	
	
	public void runGeneticEngine()
	{
		
//		for(group1_KalahHeuristic heuristic: current_generation ){
//			System.out.println(heuristic);
//		}
		
		current_generation = geneticEngine.run_game(current_generation);
		
		//save the current generation after each run
		
		System.out.println("Starting manual garbage collection.");
		long start = System.nanoTime();
		System.gc();
		long end = System.nanoTime();
		
		long elapsed = (end - start) / 1000000000;
		System.out.println("garbage collection time in seconds: \t" + elapsed);
		
		saveCurrentGeneration();
	}

	
	/* testing method
	 * 
	 * 
	public static void main(String args[]) throws Exception 
	{
		int iteration = 0;
		boolean dontQuit = true;
		
		int num_villages = 10;
		
		ArrayList<LearningEngine> engines = new ArrayList<LearningEngine>();
		
		for(int i = 0; i < num_villages; i++)
		{
			LearningEngine engine = new LearningEngine(i);
			engines.add(engine);
		}
		
		//number of game iterations before villages mix populations
		int recombination_threshhold = 10;
		
		//count of iterations since the last village recombination
		int iteration_count = 0;
		
		LearningEngine engine = new LearningEngine(village_id);
		new QuitFrame();
		
		while(dontQuit)
		{
			System.out.println("Beginning iteration: " + iteration);
			engine.runGeneticEngine();
			iteration++;
			iteration_count++;
		}
		
		
		
	}
	
	*/
	
}
